home *** CD-ROM | disk | FTP | other *** search
- #ifdef PowerPlant_PCH
- #include PowerPlant_PCH
- #endif
-
- #include <LString.h>
- #include <PP_Resources.h>
-
- #include <PP_Types.h>
- #include <PP_Constants.h>
- #include <stdio.h>
- #include <MacMemory.h>
- #include <OpenTransport.h>
- #include <OpenTransportProviders.h>
- #include <string.h>
-
- #include "IPTypes.h"
- #include "SortFrames.h"
- #include "myDns.h"
-
- extern bool gAllDomains;
-
- #define USE_UDP 1
-
- // relium is: 216.92.237.137
- const UInt32 kMagicReliumAddress = 0xD85CED89;
-
- // 209.153.140.221
- const UInt32 kMagicIPAddress = 0xD1998CDD;
-
- int BuildResponse( msg_descriptor_t *md, unsigned char *outputBuffer );
- Boolean PutDName(msg_descriptor_t* md, ConstStr255Param inStr);
- int SendDNSResponse( unsigned char *outputBuffer, UInt32 bytesToWrite );
- void ConvertIPToName( UInt32 ip, char *ipname );
- void CopyPtoC( const unsigned char *, char * );
-
- void ConsumePacket( Packet *packet, UInt32 inSize )
- {
- // if( packet->protocol != 6 ) goto toss; // only TCP packets please
- // if( ( packet->versionAndIHL & 0x0f ) != 5 ) goto toss; // minimal IP headers only (lame?)
-
- if ( (packet->protocol != 17) || (packet->dstPort != 53) )
- return;
-
- if ( packet->messageLength < 0 /* ??? */ )
- return;
-
- char ipname[64];
-
- ConvertIPToName( packet->sourceIP, ipname );
-
- printf("DNS Request from %s (port %u)\n", ipname, packet->srcPort );
-
- dns_request_t dnsRequest, *inRequest = &dnsRequest;
- msg_descriptor_t* md = &dnsRequest.md;
- dns_header_t* dnsHeader;
- UInt16 qType, qClass;
- Str255 qName;
- unsigned char outputBuffer[ 1500 ];
-
- dnsRequest.md.data = (unsigned char*) packet;
- dnsRequest.md.size = inSize;
-
- dnsHeader = (dns_header_t*)packet->data;
- dnsRequest.md.offset = 28;
-
- do {
- // ignore responses
- if (dnsHeader->queryParameter & kQueryMaskQR) break;
- // make sure there is a question
- if (dnsHeader->QDCount == 0) break;
- // skip header
- md->offset = 40; // 12 + 28
- // get the query name
- GetDName(md, qName);
- // get query type and class
- ::BlockMoveData(&((unsigned char*)packet)[md->offset], &qType, 2);
- ::BlockMoveData(&((unsigned char*)packet)[md->offset+2], &qClass, 2);
-
- // if query is a simple name lookup
- if ((qClass == kQClassIN) && (qType == kQTypeA))
- {
- printf("DNS Request from %s (port %u): %#s\n", ipname, packet->srcPort, qName );
-
- #if 0
- if ( EqualString( "\pwoz.com", qName, false, false ) ||
- EqualString( "\pwww.woz.com", qName, false, false ) ||
- EqualString( "\pwoz.org", qName, false, false ) ||
- EqualString( "\pwww.woz.org", qName, false, false ) )
- #endif
-
- bool sendIt = false;
- char tempCString[256];
-
- if ( gAllDomains )
- sendIt = true;
-
- if ( !sendIt )
- sendIt =
- ( (qName[0] > 3) &&
- ( (qName[1] == 'w') || (qName[1] == 'W')) &&
- ( (qName[2] == 'w') || (qName[2] == 'W')) &&
- ( (qName[3] == 'w') || (qName[3] == 'W')) );
-
- if ( !sendIt )
- {
- CopyPtoC( qName, tempCString );
- if ( strstr( tempCString, "doubleclick.com" ) )
- sendIt = true;
- if ( strstr( tempCString, "doubleclick.net" ) )
- sendIt = true;
- if ( strstr( tempCString, "x10.com" ) )
- sendIt = true;
- }
-
- if ( sendIt )
- {
- int bytesToWrite = BuildResponse( md, outputBuffer );
-
- int err = SendDNSResponse( outputBuffer, bytesToWrite );
- if ( err )
- printf("Error sending response %d\n", err );
- }
- }
- else if ((qClass == kQClassIN) && (qType == kQTypePTR))
- {
- //isTypePTR = true;
- }
- } while (false);
- }
-
- int BuildResponse( msg_descriptor_t *md, unsigned char *outputBuffer )
- {
- UInt16 param;
- UInt16 dataOffset = 28;
- Str255 qName;
- UInt32 theAddress = kMagicIPAddress;
- msg_descriptor_t outputMD;
-
- ::BlockMoveData( md->data, outputBuffer, md->size );
- outputMD.data = outputBuffer;
- outputMD.size = 1400;
- outputMD.offset = md->offset;
-
- // build response
- // we start with the original query
- // set parameter to indicate a response
- param = kQueryMaskQR;
- ::BlockMoveData(¶m, &outputMD.data[dataOffset+2], 2);
- // indicate 1 answer
- param = 1;
- ::BlockMove(¶m, &outputMD.data[dataOffset+6], 2);
- // we leave the question as received
- // get query name
- outputMD.offset = dataOffset+12; // start of question
- (void) GetDName(&outputMD, qName);
- outputMD.offset += 4; // skip the qType and qClass
-
- // now we're ready to start loading our answer
-
- // repeat the query name as the resource owner
- PutDName(&outputMD, qName);
-
- // continue filling in answer Resource Record
- dns_record_t* rr;
- rr = (dns_record_t*)&outputMD.data[outputMD.offset];
- rr->rdType = kQTypeA;
- rr->rdClass = kQClassIN;
- rr->rdTTL = 1;
- rr->rdLength = 4;
- outputMD.offset += 10;
- // write our address response
- ::BlockMoveData(&theAddress, &outputMD.data[outputMD.offset], 4);
- outputMD.offset += 4;
- // set message length
- outputMD.size = outputMD.offset;
-
- return outputMD.size;
- }
-
- // ---------------------------------------------------------------------------
- // • GetDName
- // ---------------------------------------------------------------------------
- // Convert a sequence of labels in Name Server format to a name string
- // Return false if name exceeds maximum length (255)
- // or contains an invalid pointer.
- Boolean GetDName(msg_descriptor_t* md, Str255 outStr)
- {
- LStr255 name;
- Str255 label;
- UInt8 len;
- UInt16 offset, pointer, oldPointer, nameLength;
- UInt16* dp;
- Boolean isPointer;
-
- name = "\p"; // initialize name
- nameLength = 0;
- offset = md->offset;
- isPointer = false;
-
- len = md->data[offset];
- // copy each label until end of name indicated by 0
- while (len) {
- // is it a pointer?
- if (len >= 64) {
- // yes, get pointer
- if (!isPointer) {
- dp = (UInt16*)&md->data[offset]; // cast to 16-bit quantity
- offset += 2; // advance current offset past pointer
- } else {
- dp = (UInt16*)&md->data[pointer]; // cast to 16-bit quantity
- }
- oldPointer = pointer;
- pointer = dp[0] & 0x3FFF; // get new pointer
- // pointers must refer to a prior occurance of the same name
- // reject garbage pointers and pointer loops (defensive)
- if (!isPointer && (pointer >= offset)) return false;
- if (isPointer && (pointer >= oldPointer)) return false;
- isPointer = true;
- } else {
- // no, copy label
- if (!isPointer) {
- LString::CopyPStr(&md->data[offset], label, 64);
- offset += len + 1; // advance offset past label
- } else {
- LString::CopyPStr(&md->data[pointer], label, 64);
- pointer += len + 1; // advance pointer past label
- }
- // add label to name
- name += label;
- name += "\p."; // append a dot
- // check for valid length (defensive)
- nameLength += len + 1;
- if (nameLength > 255) return false;
- }
- // prepare to get next label
- if (!isPointer) len = md->data[offset];
- else len = md->data[pointer];
- }
- // if not a pointer, skip terminating zero
- if (!isPointer) offset += 1;
- // update ioOffset
- md->offset = offset;
-
- // remove final dot from end of name
- len = name.Length();
- if (len != 0) name.Remove(len, 1);
- // return the resulting name
- LString::CopyPStr(name, outStr, 255);
- return true;
- }
-
- // ---------------------------------------------------------------------------
- // • PutDName
- // ---------------------------------------------------------------------------
- // Write a domain name in Name Server format
- // as a sequence of labels.
- // Return false if name won't fit in message.
- Boolean PutDName(msg_descriptor_t* md, ConstStr255Param inStr)
- {
- LStr255 name, label;
- UInt8 start, pos;
- UInt16 offset;
- UInt8* inMessage;
-
- inMessage = md->data;
- name = inStr;
- offset = md->offset;
- // copy each segment separated by '.' as a PString
- start = 1;
- pos = name.Find('.', start);
- while (pos != 0) {
- label.Assign(name, start, pos-start);
- if ((label.Length() + offset) >= md->size) return false;
- LString::CopyPStr(label, &inMessage[offset]);
- offset += pos-start + 1;
- start = pos + 1;
- pos = name.Find('.', start);
- }
- // get last segment
- label.Assign(name, start);
- if ((label.Length() + offset) >= (md->size-1)) return false;
- LString::CopyPStr(label, &inMessage[offset]);
- offset += label[0] + 1; // adjust offset to include length
- // mark the end if necessary
- if (label[0] != 0) {
- inMessage[offset] = 0;
- offset += 1;
- }
-
- // set new offset
- md->offset = offset;
- return true;
- }
-
- EndpointRef gEndpoint;
- bool gEndpointOpen = false;
-
- int InitializeResponses()
- {
- long err = 0;
- TEndpointInfo endpointInfo;
-
- if ( gEndpointOpen ) return(0);
-
- #ifdef USE_UDP
- gEndpoint = ::OTOpenEndpoint( ::OTCreateConfiguration(kUDPName), 0, &endpointInfo, &err );
- #else
- gEndpoint = ::OTOpenEndpoint( ::OTCreateConfiguration(kRawIPName), 0, &endpointInfo, &err );
- #endif
-
- if ( err ) return( err );
- gEndpointOpen = true;
-
- TBind reqAddr, retAddr;
- InetAddress addr, addr2;
-
- addr.fAddressType = AF_INET;
- addr.fPort = 53;
- addr.fHost = 0;
- // addr.fUnused = ;
-
- reqAddr.addr.maxlen = sizeof(InetAddress);
- reqAddr.addr.len = sizeof(InetAddress);;
- reqAddr.addr.buf = (unsigned char*) &addr;
- reqAddr.qlen = 0;
-
- retAddr.addr.maxlen = sizeof(InetAddress);
- retAddr.addr.len = sizeof(InetAddress);
- retAddr.addr.buf = (unsigned char*) &addr2;
- retAddr.qlen = 0;
-
- err = ::OTBind( gEndpoint, &reqAddr, &retAddr );
- if ( err ) return( err );
-
- #ifndef USE_UDP
- // set to raw mode
- TOptMgmt req;
- TOption* opt;
- UInt8 OptionBuf[ kOTFourByteOptionSize ];
-
- opt = (TOption*) OptionBuf;
- req.opt.buf = OptionBuf;
- req.opt.len = sizeof(OptionBuf);
- req.opt.maxlen = sizeof(OptionBuf);
- req.flags = T_NEGOTIATE;
-
- opt->level = INET_IP;
- opt->name = 255; // IPPROTO_RAW (per docs)
- opt->len = kOTFourByteOptionSize;
- *(UInt32*)opt->value = true;
-
- err = ::OTOptionManagement(gEndpoint, &req, &req );
- #endif
-
- return( err );
- }
-
- void CleanupResponses()
- {
- if ( gEndpointOpen )
- {
- gEndpointOpen = false;
- ::OTCloseProvider( gEndpoint );
- }
- }
-
- int SendDNSResponse( unsigned char *outputBuffer, UInt32 bytesToWrite )
- {
- Packet *p = (Packet*) outputBuffer;
- int err = 0;
-
- printf("Sending DNS Reponse.\n\n");
-
- // swap source/dest IP addresses
- UInt32 temp = p->sourceIP;
- p->sourceIP = p->destIP;
- p->destIP = temp;
- p->messageLength = bytesToWrite;
-
- // swap source/dest ports
- p->dstPort = p->srcPort;
- p->srcPort = 53;
-
- TUnitData data;
- InetAddress destAddr;
-
- destAddr.fAddressType = AF_INET;
- destAddr.fHost = p->destIP;
- destAddr.fPort = p->dstPort;
- //destAddr.fUnused;
-
- data.addr.maxlen = sizeof(InetAddress);
- data.addr.len = sizeof(InetAddress);
- data.addr.buf = (unsigned char*) &destAddr;
- data.opt.maxlen = 0;
- data.opt.len = 0;
- data.opt.buf = 0;
- data.udata.maxlen = bytesToWrite;
- data.udata.len = bytesToWrite;
-
- #ifdef USE_UDP
- data.udata.buf = 28 + (unsigned char*)outputBuffer;
- #else
- data.udata.buf = (unsigned char*)outputBuffer;
- #endif
-
- err = OTSndUData( gEndpoint, &data );
- return( err );
- }
-
-
-
- void ConvertIPToName( UInt32 ip, char *ipname )
- {
- unsigned char *p = (unsigned char*) &ip;
- sprintf( ipname, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- }
-
- void CopyPtoC( const unsigned char *src, char *dst )
- {
- BlockMoveData( src+1, dst, *src );
- dst[*src] = 0;
- }
-